package com.lengyu.iottransfer.gateway.udp;

import com.alibaba.fastjson.JSONObject;
import com.lengyu.iottransfer.gateway.common.ByteUtils;
import com.lengyu.iottransfer.gateway.config.MqttSendGateway;
import com.lengyu.iottransfer.gateway.entity.DeviceTransfer;
import com.lengyu.iottransfer.gateway.redis.RedisUtils;
import com.lengyu.iottransfer.gateway.service.IDeviceTransferService;
import com.lengyu.iottransfer.gateway.service.impl.ElecLcdTransferService;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetSocketAddress;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

@Component
public class UdpServerHandlerForLcd  extends SimpleChannelInboundHandler<DatagramPacket> {
    private final static Logger logger = LoggerFactory.getLogger(UdpServerHandlerForLcd.class);

    @Resource
    private MqttSendGateway mqttSendGateway;

    @Autowired
    IDeviceTransferService deviceTransferService;

    @Autowired
    ElecLcdTransferService elecLcdTransferService;

    public static UdpServerHandlerForLcd udpServerHandler;

    @Autowired
    private RedisUtils redisUtils;

    @PostConstruct
    public void init(){
        udpServerHandler = this;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception {
        InetSocketAddress sender = datagramPacket.sender();
        String ip = sender.getAddress().getHostAddress();
        ByteBuf buf = datagramPacket.content().copy();
        try {
            byte[] data = new byte[buf.readableBytes()];
            buf.readBytes(data);
            String hexStr = ByteUtils.byteArrayToHexString(data);

//            logger.info("收到IP：{},发送的数据：{}", ip, data);
            // 下面进行业务代码处理
            byte[] data1 = new byte[data.length -4];
            System.arraycopy(data,0,data1,0,data1.length);
//            logger.info("crc32计算:" + data1);
            String crc32 = ByteUtils.getCRC32Hex(data1);
//            logger.info("crc32计算结果:" + crc32);
            String oldCrc32 = hexStr.substring((hexStr.length() - 11));
//            logger.info("crc32发送内容:" + oldCrc32);
            if(crc32.equals(oldCrc32)) {
                if(hexStr.startsWith("f1 b0")){
//                //注册消息
                    //返回握手信息
                    channelHandlerContext.channel().writeAndFlush(
                            new DatagramPacket(Unpooled.copiedBuffer(ByteUtils.hexStrToByteArray(getHandShakeRet())),
                                    datagramPacket.sender()));
                }
                else if(hexStr.startsWith("f1 b2")){
                    //网络消息 返回信息
                    channelHandlerContext.channel().writeAndFlush(
                            new DatagramPacket(Unpooled.copiedBuffer(ByteUtils.hexStrToByteArray(getNetMessageRet())),
                                    datagramPacket.sender()));
                }
                else if(hexStr.startsWith("f1 b4")){
                    //节点消息
                    channelHandlerContext.channel().writeAndFlush(
                            new DatagramPacket(Unpooled.copiedBuffer(ByteUtils.hexStrToByteArray(getNodeMessageRet())),
                                    datagramPacket.sender()));
                }
                else if(hexStr.startsWith("f1 ac")){
                    //实时消息
                    logger.info("收到IP：{},发送的数据：{}", ip, hexStr);
                    decodeCurrent(data);
                    channelHandlerContext.channel().writeAndFlush(
                            new DatagramPacket(Unpooled.copiedBuffer(ByteUtils.hexStrToByteArray(getCurrentMessageRet())),
                                    datagramPacket.sender()));
                }
                else if(hexStr.startsWith("f1 a4")){
                    //事件
                    channelHandlerContext.channel().writeAndFlush(
                            new DatagramPacket(Unpooled.copiedBuffer(ByteUtils.hexStrToByteArray(getEventMessageRet())),
                                    datagramPacket.sender()));
                }

                else if(hexStr.startsWith("f1 a8")){
                    //统计消息
                    channelHandlerContext.channel().writeAndFlush(
                            new DatagramPacket(Unpooled.copiedBuffer(ByteUtils.hexStrToByteArray(getStatisticsMessageRet())),
                                    datagramPacket.sender()));
                }

                else if(hexStr.startsWith("f1 aa")){
                    //心跳
                    channelHandlerContext.channel().writeAndFlush(
                            new DatagramPacket(Unpooled.copiedBuffer(ByteUtils.hexStrToByteArray(getHeartMessageRet())),
                                    datagramPacket.sender()));
                }
                else{
                    logger.info("未知消息类型：" + hexStr.substring(0,5));
                }


            }
            else{
                logger.info("收到IP：{},发送的非法数据：{}", ip, hexStr);
            }


        }catch (Exception e){
            e.printStackTrace();
        }
        buf.release();
        // TCP返回数据写法
        //channelHandlerContext.channel().writeAndFlush("1");
        // UDP返回数据写法

    }

    /**
     * 解析实时状态获取电量信息
     * @param data
     */
    private void decodeCurrent(byte[] data){
        String mac = ByteUtils.byteArrayToHexString(data,8,6,false);
        logger.info("mac地址：" + mac);
        int nodeCount = data[2] & 0xff;
        logger.info("节点数：" + nodeCount);
        for(int i=0;i<nodeCount;i++){
           String  nodeAddr = ByteUtils.byteToHex(data[20 + i*32]);
           int  type = data[21+ i*32] & 0xff;
           long energy = ByteUtils.byteArrayToUnsignedLong(data,20+28+32*i);

//            logger.info("节点: " + nodeAddr + "  type: " + type + "  电能：" + energyBigDecimal);
            if(type == 132){
                String code = (mac+ "MN"+ nodeAddr).toUpperCase(Locale.ROOT) ;
//                logger.info("开始查找转化信息：" + code);
                DeviceTransfer deviceTransfer = udpServerHandler.deviceTransferService.getDeviceTransferByCode(code);
//                logger.info("查找结束：" + code);
                if(deviceTransfer == null){
                    logger.info("不存在该设备：" + code);
                    continue;
                }
                BigDecimal energyBigDecimal = (BigDecimal.valueOf(energy).divide(BigDecimal.valueOf(1000),2, RoundingMode.HALF_UP)).add(deviceTransfer.getBaseValue());
                logger.info("节点: " + nodeAddr + "  type: " + type + "  电能：" + energyBigDecimal + "baseValue: " + deviceTransfer.getBaseValue());
                //正向有功电能
                JSONObject json = new JSONObject();
                JSONObject paramJson = new JSONObject();
                paramJson.put("positiveActiveEnergy",energyBigDecimal);
                json.put("id",System.currentTimeMillis());
                json.put("method","thing.event.property.post");
                json.put("params",paramJson);

                if(deviceTransfer != null){
                    //发送消息到IITA平台
//                    logger.info("开始校验消息40分钟内是否发送过：" + deviceTransfer.getCode());
                    String lastFlag = udpServerHandler.redisUtils.get("propertyPostTime:" + deviceTransfer.getCode());
//                    logger.info("校验结束：" + deviceTransfer.getCode());
                    if(StringUtils.isNotBlank(lastFlag)){
                        //一段时间内如果发送过信息，将不在发送
//                        logger.info("未到40分钟不发消息：" + deviceTransfer.getCode() + " lastflag:" + lastFlag);
                        continue;
                    }

                    logger.info("发送消息到第三方平台:" + json.toJSONString());
                    udpServerHandler.elecLcdTransferService.checkConnectFlag(deviceTransfer);
//                    udpServerHandler.mqttSendGateway.sendToMqtt(udpServerHandler.deviceTransferService.getThirdPlatPostPropertyTopic(deviceTransfer), json.toJSONString());
                    //发送消息到自己平台
                    udpServerHandler.mqttSendGateway.sendToMqtt(udpServerHandler.deviceTransferService.getIotPlatPropertyTopic(deviceTransfer), json.toJSONString());
                    logger.info("发送消息到第三方平台完成");
                    udpServerHandler.redisUtils.set("propertyPostTime:" + deviceTransfer.getCode(),String.valueOf(System.currentTimeMillis()),40, TimeUnit.MINUTES);
                }

            }
        }


    }

    private String getHandShakeRet(){
        StringBuilder retSb = new StringBuilder();
        retSb.append("f1 b0 ac 00 00 00 00 01 ");
        retSb.append(ByteUtils.longToHexStr(System.currentTimeMillis()/1000)).append(" ");
        retSb.append("ff ff ff a0 ");
        String crc32 = ByteUtils.getCRC32Hex(retSb.toString());
        retSb.append(crc32);
//        logger.info("握手返回信息:" + retSb.toString());
        return retSb.toString();
    }


    private String getNetMessageRet(){
        StringBuilder retSb = new StringBuilder();
        retSb.append("f1 b2 01 00 00 00 00 03 ");
        retSb.append(ByteUtils.longToHexStr(System.currentTimeMillis()/1000)).append(" ");
        retSb.append("ff ff ff a0 ");
        String crc32 = ByteUtils.getCRC32Hex(retSb.toString());
        retSb.append(crc32);
//        logger.info("网络消息返回信息:" + retSb.toString());
        return retSb.toString();
    }

    private String getNodeMessageRet(){
        StringBuilder retSb = new StringBuilder();
        retSb.append("f1 b4 00 00 00 00 00 04 ");
        retSb.append(ByteUtils.longToHexStr(System.currentTimeMillis()/1000)).append(" ");
        retSb.append("ff ff ff a0 ");
        String crc32 = ByteUtils.getCRC32Hex(retSb.toString());
        retSb.append(crc32);
        logger.info("节点消息返回信息:" + retSb.toString());
        return retSb.toString();
    }

    private String getCurrentMessageRet(){
        StringBuilder retSb = new StringBuilder();
        retSb.append("f1 ac 03 00 00 00 00 05 ");
        retSb.append(ByteUtils.longToHexStr(System.currentTimeMillis()/1000)).append(" ");
        retSb.append("ff ff ff a0 ");
        String crc32 = ByteUtils.getCRC32Hex(retSb.toString());
        retSb.append(crc32);
//        logger.info("当前状态返回信息:" + retSb.toString());
        return retSb.toString();
    }

    private String getEventMessageRet(){
        StringBuilder retSb = new StringBuilder();
        retSb.append("f1 ac 03 00 00 00 00 10 ");
        retSb.append(ByteUtils.longToHexStr(System.currentTimeMillis()/1000)).append(" ");
        retSb.append("ff ff ff a0 ");
        String crc32 = ByteUtils.getCRC32Hex(retSb.toString());
        retSb.append(crc32);
//        logger.info("事件消息返回信息:" + retSb.toString());
        return retSb.toString();
    }

    private String getStatisticsMessageRet(){
        StringBuilder retSb = new StringBuilder();
        retSb.append("f1 a8 f1 00 00 00 50 be ");
        retSb.append(ByteUtils.longToHexStr(System.currentTimeMillis()/1000)).append(" ");
        retSb.append("ff ff ff a0 ");
        String crc32 = ByteUtils.getCRC32Hex(retSb.toString());
        retSb.append(crc32);
//        logger.info("统计消息返回信息:" + retSb.toString());
        return retSb.toString();
    }

    private String getHeartMessageRet(){
        StringBuilder retSb = new StringBuilder();
        retSb.append("f1 aa 00 00 00 00 50 f5 ");
        retSb.append(ByteUtils.longToHexStr(System.currentTimeMillis()/1000)).append(" ");
        retSb.append("ff ff ff a0 ");
        String crc32 = ByteUtils.getCRC32Hex(retSb.toString());
        retSb.append(crc32);
//        logger.info("心跳消息返回信息:" + retSb.toString());
        return retSb.toString();
    }
}
